package com.cykj.common.utils;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @BelongsProject: smart_recruit_backend
 * @BelongsPackage: com.cykj.common.utils
 * @Author: 小白糖糖
 * @CreateTime: 2025-08-29 10:59
 * @Description: TODO
 * @Version: 1.0
 */
@Component // 标记为Spring组件，确保全局唯一实例
public class SnowflakeUtil {

    // 注入端口号（Spring容器会自动赋值）
    @Value("${server.port}")
    private int port;

    private String ip;

    // 算法参数
    private final long epoch = 1609459200000L; // 2021-01-01 00:00:00
    private final long datacenterIdBits = 5L;
    private final long workerIdBits = 5L;
    private final long sequenceBits = 12L;

    private final long maxDatacenterId = ~(-1L << datacenterIdBits);
    private final long maxWorkerId = ~(-1L << workerIdBits);
    private final long sequenceMask = ~(-1L << sequenceBits);

    private final long workerIdShift = sequenceBits;
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    private final long timestampShift = sequenceBits + workerIdBits + datacenterIdBits;

    private long datacenterId;
    private long workerId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    // 构造方法：Spring会自动调用，初始化datacenterId和workerId
    public SnowflakeUtil() {
        this.datacenterId = getDataCenterId();
        this.workerId = getWorkerId();
        validateIds();
    }

    // 校验ID合法性
    private void validateIds() {
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException("Invalid datacenterId: " + datacenterId);
        }
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException("Invalid workerId: " + workerId);
        }
    }

    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate ID.");
        }

        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = waitForNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        return ((timestamp - epoch) << timestampShift) |
                (datacenterId << datacenterIdShift) |
                (workerId << workerIdShift) |
                sequence;
    }

    private long waitForNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    private int getWorkerId() {
        try {
            String[] ips = ip.split("\\.");
            if(ips.length != 4){
                return 0;
            }
            int lastIp = Integer.parseInt(ips[ips.length - 1]);
            return (lastIp + port) % 32;
        } catch (NumberFormatException e) {
            return 1;
        }

    }

    private int getDataCenterId() {
        try {
            ip = InetAddress.getLocalHost().getHostAddress();
            // 根据IP段区分数据中心
            if (ip.startsWith("10.1.")) {
                return 0; // 北京机房
            } else if (ip.startsWith("10.2.")) {
                return 1; // 上海机房
            } else if (ip.startsWith("10.3.")) {
                return 2; // 广州机房
            } else {
                return 3; // 默认机房
            }
        } catch (UnknownHostException e) {
            throw new RuntimeException("Failed to get dataCenterId", e);
        }
    }
}

